package com.campus.payment.controller;

import cn.hutool.json.JSONUtil;
import com.campus.common.bean.common.Resp;
import com.campus.payment.config.WechatPayConfig;
import com.campus.payment.dto.RefundRequestDTO;
import com.campus.payment.dto.RefundResponseDTO;
import com.campus.payment.service.RefundRecordService;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RSAPublicKeyNotificationConfig;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.refund.model.RefundNotification;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.stream.Collectors;

/**
 * <p>
 * 退款控制器
 * </p>
 *
 * @author ZhaoYuJie
 * @since 2025-01-15
 */
@RestController
@RequestMapping("/refund")
@Api(tags = "退款管理")
@Slf4j
public class RefundController {

    @Autowired
    private RefundRecordService refundRecordService;

    @Autowired
    private WechatPayConfig wechatPayConfig;

    /**
     * 申请退款
     */
    @PostMapping("/apply")
    @ApiOperation("申请退款")
    public Resp<RefundResponseDTO> applyRefund(@Valid @RequestBody RefundRequestDTO requestDTO) {
        try {
            RefundResponseDTO responseDTO = refundRecordService.applyRefund(requestDTO);
            return Resp.success(responseDTO);
        } catch (Exception e) {
            log.error("退款申请失败", e);
            return Resp.error("退款申请失败: " + e.getMessage());
        }
    }

    /**
     * 根据订单ID查询退款记录
     */
    @GetMapping("/order/{orderId}")
    @ApiOperation("根据订单ID查询退款记录")
    public Resp<RefundResponseDTO> getRefundByOrderId(@PathVariable String orderId) {
        try {
            RefundResponseDTO responseDTO = refundRecordService.getRefundByOrderId(orderId);
            if (responseDTO == null) {
                return Resp.error("未找到退款记录");
            }
            return Resp.success(responseDTO);
        } catch (Exception e) {
            log.error("查询退款记录失败", e);
            return Resp.error("查询退款记录失败: " + e.getMessage());
        }
    }

    /**
     * 微信退款回调
     */
    @PostMapping("/wechatRefundNotify")
    @ApiOperation("微信退款回调")
    public ResponseEntity<String> wechatRefundNotify(HttpServletRequest request) {
        try {
            // 获取请求头信息
            String wechatpayTimestamp = request.getHeader("Wechatpay-Timestamp");
            String wechatpayNonce = request.getHeader("Wechatpay-Nonce");
            String wechatpaySignature = request.getHeader("Wechatpay-Signature");
            String wechatpaySerial = request.getHeader("Wechatpay-Serial");
            
            // 获取请求体
            String requestBody = getRequestBody(request);
            
            log.info("收到微信退款回调，时间戳: {}, 随机串: {}, 序列号: {}", 
                wechatpayTimestamp, wechatpayNonce, wechatpaySerial);
            
            // 构建请求参数
            RequestParam requestParam = new RequestParam.Builder()
                    .serialNumber(wechatpaySerial)
                    .nonce(wechatpayNonce)
                    .signature(wechatpaySignature)
                    .timestamp(wechatpayTimestamp)
                    .body(requestBody)
                    .build();
            
            // 使用微信支付公钥初始化 NotificationConfig
            NotificationConfig config = new RSAPublicKeyNotificationConfig.Builder()
                    .publicKeyFromPath(wechatPayConfig.getPublicKeyPath())
                    .publicKeyId(wechatPayConfig.getPublicKeyId())
                    .apiV3Key(wechatPayConfig.getApiV3Key())
                    .build();

            // 初始化通知解析器
            NotificationParser parser = new NotificationParser(config);
            
            // 解析退款通知
            RefundNotification notification = parser.parse(requestParam, RefundNotification.class);
            log.info("微信退款回调，退款通知: {}", JSONUtil.toJsonStr(notification));
            
            // 处理退款回调
            boolean success = refundRecordService.handleRefundCallback(
                notification.getRefundId(),
                notification.getRefundStatus().name(),
                notification.getSuccessTime()
            );
            
            if (success) {
                log.info("微信退款回调处理成功，退款单号: {}, 状态: {}", 
                    notification.getRefundId(), notification.getRefundStatus());
                // 微信退款回调成功时返回HTTP 200状态码和空响应体
                return ResponseEntity.ok().build();
            } else {
                log.error("微信退款回调处理失败，退款单号: {}", notification.getRefundId());
                // 微信退款回调失败时返回HTTP 400状态码和指定的JSON报文
                String failResponse = "{\"code\":\"FAIL\",\"message\":\"失败\"}";
                return ResponseEntity.badRequest().body(failResponse);
            }
            
        } catch (Exception e) {
            log.error("微信退款回调处理异常", e);
            // 微信退款回调异常时返回HTTP 500状态码和指定的JSON报文
            String failResponse = "{\"code\":\"FAIL\",\"message\":\"失败\"}";
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(failResponse);
        }
    }
    
    /**
     * 获取请求体内容
     */
    private String getRequestBody(HttpServletRequest request) throws IOException {
        try (BufferedReader reader = request.getReader()) {
            return reader.lines().collect(Collectors.joining(System.lineSeparator()));
        }
    }

}